package io.itit.ecp.admin.common.utils;

import cn.hutool.core.date.DateUtil;
import io.itit.ecp.admin.common.constants.EcpAdminConstants;
import io.itit.ecp.admin.common.enums.StatisticsModeEnums;
import io.itit.grass.common.utils.Y666Utils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class EcpAdminUtils {

    public static String key(String delimiter, String... str) {
        return str == null || str.length == 0 ? "" : Arrays.stream(str).map(String::toUpperCase).collect(Collectors.joining(delimiter));
    }

    public static String keyColon(String... str) {
        return key(EcpAdminConstants.COLON, str);
    }

    public static String joiner(Collection<String> sceneList) {
        return CollectionUtils.isEmpty(sceneList) ? "" : sceneList.stream().collect(Collectors.joining(EcpAdminConstants.COMMA));
    }

    public static List<String> parse(String sceneList) {
        return StringUtils.isEmpty(sceneList) ? Collections.emptyList() : Arrays.asList(sceneList.split(EcpAdminConstants.COMMA));
    }

    public static String format(Date date, String mode) {
        return Y666Utils.format(date, StatisticsModeEnums.javaDateFormat(mode));
    }


    /**
     * 构建指定范围的日期
     *
     * @param start yyyy-MM-dd
     * @param end   yyyy-MM-dd
     * @return
     */
    public static List<String> dateStr(String start, String end, String mode) {
        Date dateStart = Y666Utils.parseYyyyMmDd(start);
        Date dateEnd = Y666Utils.parseYyyyMmDdHhMmSs(Y666Utils.concat232359(end));
        // 如果大于当前时间，就给当前时间
        dateEnd = dateEnd.compareTo(new Date()) >= 0 ? new Date() : dateEnd;
        if (dateEnd.compareTo(dateStart) < 0) {
//            GrassException.throwEx("结束日期不能小于开始日期！");
            return new ArrayList<>();
        }

        // 时
        if (StatisticsModeEnums.hour.mode.equals(mode)) {
            Long hours = durationBetween(dateStart, dateEnd).toHours();
            return IntStream.range(0, hours.intValue() + 1)
                    .mapToObj(t -> Y666Utils.format(DateUtils.addHours(dateStart, t), "MM/dd HH:00"))
                    .collect(Collectors.toList());
        }
        // 日
        if (StatisticsModeEnums.day.mode.equals(mode)) {
            Long days = durationBetween(dateStart, dateEnd).toDays();
            return IntStream.range(0, days.intValue() + 1)
                    .mapToObj(t -> Y666Utils.format(DateUtils.addDays(dateStart, t), StatisticsModeEnums.day.javaDateFormat))
                    .collect(Collectors.toList());
        }

        // 月
        if (StatisticsModeEnums.month.mode.equals(mode)) {
            return IntStream.range(0, between(DateUtil.beginOfMonth(dateStart), DateUtil.endOfMonth(dateEnd), ChronoUnit.MONTHS).intValue() + 1)
                    .mapToObj(t -> Y666Utils.format(DateUtils.addMonths(dateStart, t), StatisticsModeEnums.month.javaDateFormat))
                    .collect(Collectors.toList());
        }

        // 年
        return IntStream.range(0, between(DateUtil.beginOfYear(dateStart), DateUtil.endOfYear(dateEnd), ChronoUnit.YEARS).intValue() + 1)
                .mapToObj(t -> Y666Utils.format(DateUtils.addYears(dateStart, t), StatisticsModeEnums.year.javaDateFormat))
                .collect(Collectors.toList());
    }

    /**
     * 比较两个日期年的差值和月差值
     *
     * @param dateStart
     * @param dateEnd
     * @param unit
     * @return
     */
    public static Long between(Date dateStart, Date dateEnd, ChronoUnit unit) {
        LocalDate localDateStart = dateStart.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate localDateEnd = dateEnd.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return unit.between(localDateStart, localDateEnd);
    }

    /**
     * 比较两个日期天的差值和小时差值
     *
     * @param dateStart
     * @param dateEnd
     * @return
     */
    public static Duration durationBetween(Date dateStart, Date dateEnd) {
        LocalDateTime localDateStart = dateStart.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime localDateEnd = dateEnd.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        return Duration.between(localDateStart, localDateEnd);
    }

    public static void main(String[] args) {
        System.out.println("===================================== hour");
        dateStr("2023-12-29", "2024-01-02", StatisticsModeEnums.hour.mode).forEach(System.out::println);
        System.out.println("===================================== day");
        dateStr("2023-11-22", "2024-01-04", StatisticsModeEnums.day.mode).forEach(System.out::println);
        System.out.println("===================================== month");
        dateStr("2023-10-04", "2024-01-04", StatisticsModeEnums.month.mode).forEach(System.out::println);
        System.out.println("===================================== year");
        dateStr("2021-12-10", "2024-01-04", StatisticsModeEnums.year.mode).forEach(System.out::println);
        System.out.println("===================================== end");
    }

}
